﻿using Micro.Core.Options;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace Micro.AspNetCore
{
    /// <summary>
    /// <see cref="IServiceCollection"/>扩展方法
    /// </summary>
    public static class ServiceExtensions
    {
        #region IServiceCollection

        /// <summary>
        /// 获取<see cref="IHostingEnvironment"/>环境信息
        /// </summary>
        public static IWebHostEnvironment GetWebHostEnvironment(this IServiceCollection services)
        {
            return services.GetSingletonInstance<IWebHostEnvironment>();
        }

        #endregion

        #region IServiceProvider

        /// <summary>
        /// 获取HttpContext实例
        /// </summary>
        public static HttpContext HttpContext(this IServiceProvider provider)
        {
            IHttpContextAccessor accessor = provider.GetService<IHttpContextAccessor>();
            return accessor?.HttpContext;
        }

        /// <summary>
        /// 当前业务是否处于HttpRequest中
        /// </summary>
        public static bool InHttpRequest(this IServiceProvider provider)
        {
            var context = provider.HttpContext();
            return context != null;
        }

        #endregion


        /// <summary>
        /// 添加配置
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configuration"></param>
        /// <returns></returns>
        public static IServiceCollection AddConfigOptions(this IServiceCollection services, IConfiguration configuration)
        {
            MicroOptions microOptions = new MicroOptions();

            HostOptions hostOptions = new HostOptions();
            configuration.GetSection("Host").Bind(hostOptions);
            services.AddSingleton(hostOptions);

            ServiceDiscoveryOption serviceDiscovery = new ServiceDiscoveryOption();
            configuration.GetSection("ServiceDiscovery").Bind(serviceDiscovery);
            services.AddSingleton(serviceDiscovery);

            DbConfig dbConfig = new DbConfig();
            configuration.GetSection("DbConfig").Bind(dbConfig);
            if (dbConfig.DbOptions == null)
                dbConfig.DbOptions = new List<DbOption>();
            services.AddSingleton(dbConfig);

            microOptions.Host = hostOptions;
            microOptions.ServiceDiscovery = serviceDiscovery;
            microOptions.DbConfig = dbConfig;

            services.AddSingleton(microOptions);
            return services;
        }

        /// <summary>
        /// 动态添加服务
        /// </summary>
        /// <param name="services"></param>
        /// <param name="assemblys"></param>
        /// <param name="endsWith">后缀</param>
        public static void AddCustomServices(this IServiceCollection services, ServiceLifetime lifetime, string[] notEqualsArrys=null , string endsWith = "AppService", params Assembly[] assemblys)
        {
            if (endsWith.IsNull() || assemblys == null || assemblys.Length == 0)
                return;
            foreach (var assembly in assemblys)
            {
                if (assembly == null)
                    continue;
                var typeInfos = assembly.DefinedTypes.Where(a => a.Name.EndsWithIgnoreCase(endsWith) && !a.IsInterface);
                foreach (var type in typeInfos)
                {
                    if (type.GetInterfaces().Count() == 0)
                        services.Add(new ServiceDescriptor(type, lifetime));
                    else
                    {
                        var interfaceTypes = type.GetInterfaces().Where(m => !notEqualsArrys.EqualsIgnoreCaseArray(m.Name));
                        foreach (var interfaceType in interfaceTypes)
                        {
                            services.Add(new ServiceDescriptor(interfaceType, type, lifetime));
                        }
                    }
                }
            }
        }
    }
}
